// WebSocket启动算法模型服务
let onProcessedEvent = [];
class StartModelWebSocketService {
  /**
   * 构造函数
   * @param {string} wsUrl - WebSocket连接的URL字符串
   * @param {object} options - 配置对象
   * @param {number} options.plantId - 工厂ID，默认为68
   * @param {number} options.plantType - 工厂类型，默认为1
   * @param {number} options.copyNum - 副本编号，默认为5
   * @param {number} options.downloadPort - 下载端口，默认为18005
   * @param {number} options.monitorPort - 监控端口，默认为19005
   * @param {string} options.ip - IP地址，默认为"192.168.46.78"
   * @param {string} options.serverUrl - 服务器URL，默认为"192.168.46.78:8070/rtlab"
   * @param {string[]} options.paramList - 参数列表，默认为["2_6_0_0"]
   * @param {number} options.timeout - 连接超时时间（毫秒），默认为10000
   * @param {number} options.maxReconnectAttempts - 最大重连尝试次数，默认为3
   */
  constructor(wsUrl, options = {}) {
    // 验证必需参数
    if (!wsUrl) {
      throw new Error("WebSocket URL is required");
    }

    // 存储配置参数
    this.wsUrl = wsUrl;
    this.options = {
      plantId: options.plantId || 68,
      plantType: options.plantType || 1,
      copyNum: options.copyNum,
      downloadPort: options.downloadPort || 18005,
      monitorPort: options.monitorPort || 19005,
      ip: options.ip || "192.168.46.78",
      serverUrl: options.serverUrl || "192.168.46.78:8070/rtlab",
      timeout: options.timeout || 10000,
      maxReconnectAttempts: options.maxReconnectAttempts || 0,
      paramList: options.paramList,
    };

    // 初始化WebSocket实例
    this.ws = null;
    // 连接状态
    this.isConnected = false;
    // 连接状态枚举
    this.connectionState = {
      DISCONNECTED: "disconnected",
      CONNECTING: "connecting",
      CONNECTED: "connected",
      ERROR: "error",
    };
    // 当前连接状态
    this.currentState = this.connectionState.DISCONNECTED;
    // 消息队列，用于存储连接未建立时的消息
    this.messageQueue = [];
    // 重连尝试次数
    this.reconnectAttempts = 0;
    // 重连间隔时间(ms)
    this.reconnectInterval = 3000;
    // 连接超时定时器
    this.connectionTimer = null;
    // 事件回调函数存储
    this.callbacks = {
      onOpen: [],
      onMessage: [],
      onError: [],
      onClose: [],
      onStateChange: [],
      onData: onProcessedEvent,
    };

    // 自动连接
    this.connect();
  }

  /**
   * 建立WebSocket连接
   */
  connect() {
    // 如果已连接，则不再重复连接
    if (this.ws && this.isConnected) {
      return;
    }

    // 更新连接状态
    this.updateConnectionState(this.connectionState.CONNECTING);

    try {
      // 创建WebSocket实例
      this.ws = new WebSocket(this.wsUrl);

      // 设置连接超时
      this.connectionTimer = setTimeout(() => {
        if (!this.isConnected) {
          this.ws.close();
          this.updateConnectionState(this.connectionState.ERROR);
          this.onError({
            type: "timeout",
            message: "连接超时，请检查网络连接",
          });
        }
      }, this.options.timeout);

      /**
       * 连接打开事件处理
       */
      this.ws.onopen = (event) => {
        console.log("算法模型启动服务连接已建立");
        this.isConnected = true;
        this.reconnectAttempts = 0;
        this.updateConnectionState(this.connectionState.CONNECTED);

        // 清除连接超时定时器
        if (this.connectionTimer) {
          clearTimeout(this.connectionTimer);
          this.connectionTimer = null;
        }

        // 发送初始化消息
        this.sendInitialMessage();

        // 处理消息队列中的消息
        this.flushMessageQueue();

        // 触发onOpen回调
        this.callbacks.onOpen.forEach((callback) => callback(event));
      };

      /**
       * 接收消息事件处理
       */
      this.ws.onmessage = (event) => {
        try {
          //判断是否是json字符串
          if (!event.data.startsWith("{")) {
            console.error("收到非json字符串的错误消息:", event.data);
            return;
          }
          // 尝试解析JSON消息
          const message = JSON.parse(event.data);
          // console.log("收到算法模型启动服务消息:", message);

          // 根据消息类型处理
          this.handleMessage(message);

          // 触发onMessage回调
          this.callbacks.onMessage.forEach((callback) => callback(event));
        } catch (error) {
          console.error("消息解析失败:", error);
          this.onError({
            type: "parse_error",
            message: "消息解析失败",
            originalError: error,
          });
        }
      };

      /**
       * 错误处理
       */
      this.ws.onerror = (error) => {
        console.error("WebSocket错误:", error);
        this.updateConnectionState(this.connectionState.ERROR);
        this.callbacks.onError.forEach((callback) => callback(error));
      };

      /**
       * 连接关闭处理
       */
      this.ws.onclose = (event) => {
        console.log("算法模型启动服务连接已关闭");
        this.isConnected = false;
        this.updateConnectionState(this.connectionState.DISCONNECTED);

        // 清除连接超时定时器
        if (this.connectionTimer) {
          clearTimeout(this.connectionTimer);
          this.connectionTimer = null;
        }

        // 触发onClose回调
        this.callbacks.onClose.forEach((callback) => callback(event));

        // 尝试重连
        this.attemptReconnect();
      };
    } catch (error) {
      console.error("WebSocket连接失败:", error);
      this.updateConnectionState(this.connectionState.ERROR);
      this.onError({
        type: "connection_error",
        message: "WebSocket连接失败",
        originalError: error,
      });
    }
  }

  /**
   * 更新连接状态
   * @param {string} newState - 新的连接状态
   */
  updateConnectionState(newState) {
    if (this.currentState !== newState) {
      const oldState = this.currentState;
      this.currentState = newState;

      // 触发状态变化回调
      this.callbacks.onStateChange.forEach((callback) =>
        callback({ oldState, newState })
      );
    }
  }

  /**
   * 处理接收到的消息
   * @param {object} message - 接收到的消息对象
   */
  handleMessage(message) {
    // 根据消息类型处理
    if (message.type === "response") {
      if (message.status === "success") {
        console.log("算法模型启动成功:", message.data);
      } else {
        console.error("算法模型启动失败:", message.error);
        this.onError({
          type: "business_error",
          message: message.error || "算法模型启动失败",
          details: message,
        });
      }
    } else if (message.com && message.data && message.selected) {
      // 使用静态方法处理WebSocket消息数据
      const processedData =
        StartModelWebSocketService.processWebSocketMessage(message);
      // console.log("处理后的WebSocket消息数据:", processedData);

      // 触发自定义的数据处理事件回调
      if (this.callbacks.onData) {
        this.callbacks.onData.forEach((callback) => callback(processedData));
      }
    }
  }

  /**
   * 发送初始化消息（连接建立时自动调用）
   */
  sendInitialMessage() {
    // 导入store以获取IP地址
    import("../store/ws.js")
      .then(({ useWsStore }) => {
        const wsStore = useWsStore();

        // 获取IP地址和服务器URL
        const ip = wsStore.getIpFromUrl;
        const serverUrl = wsStore.getServerUrl;

        // 构建初始化消息
        const initMessage = {
          com: "start",
          plantId: this.options.plantId,
          serverUrl: serverUrl,
          downloadPort: 18000 + this.options.copyNum,
          copyNum: this.options.copyNum,
          ip: ip,
          monitorPort: 19000 + this.options.copyNum,
          oscSigList: [],
          paramList: this.options.paramList || ["2_6_0_0"],
          plantType: this.options.plantType,
        };

        // 发送JSON格式的消息
        this.send(JSON.stringify(initMessage));
        console.log("初始化消息已发送:", initMessage);
      })
      .catch((error) => {
        console.error("导入store失败:", error);

        // 如果store导入失败，使用备选方案获取IP
        const ip = this.extractIpFromUrl(this.wsUrl);
        const initMessage = {
          com: "start",
          plantId: this.options.plantId,
          serverUrl: `${ip}:8070/rtlab`,
          downloadPort: 18000 + this.options.copyNum,
          copyNum: this.options.copyNum,
          ip: ip,
          monitorPort: 19000 + this.options.copyNum,
          oscSigList: [],
          paramList: ["2_6_0_0"],
          plantType: this.options.plantType,
        };

        this.send(JSON.stringify(initMessage));
        console.log("初始化消息已发送（备选方案）:", initMessage);
      });
  }

  /**
   * 从URL中提取IP地址（备选方案）
   * @param {string} url - WebSocket URL
   * @returns {string} IP地址
   */
  extractIpFromUrl(url) {
    try {
      const urlObj = new URL(url);
      return urlObj.hostname;
    } catch (error) {
      // 如果URL解析失败，尝试从字符串中提取IP
      const ipMatch = url.match(/(\d+\.\d+\.\d+\.\d+)/);
      return ipMatch ? ipMatch[1] : "localhost";
    }
  }

  /**
   * 发送启动算法模型的请求
   * @param {object} params - 可选的参数覆盖对象
   */
  sendStartRequest(params = {}) {
    // 合并默认参数和传入参数
    const requestParams = {
      com: "start",
      plantId: this.options.plantId,
      serverUrl: this.options.serverUrl,
      downloadPort: this.options.downloadPort,
      copyNum: this.options.copyNum,
      ip: this.options.ip,
      monitorPort: this.options.monitorPort,
      oscSigList: [],
      paramList: ["2_6_0_0"],
      plantType: this.options.plantType,
      ...params,
    };

    // 发送JSON格式的消息
    this.send(JSON.stringify(requestParams));
    console.log("算法模型启动请求已发送:", requestParams);
  }

  /**
   * 发送消息到WebSocket服务器
   * @param {string|object} message - 要发送的消息
   */
  send(message) {
    // 如果消息是对象，转换为JSON字符串
    const messageToSend =
      typeof message === "object" ? JSON.stringify(message) : message;

    // 如果已连接且WebSocket处于OPEN状态，则直接发送
    if (this.isConnected && this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(messageToSend);
    } else {
      // 否则将消息加入队列，等待连接建立后发送
      console.warn("WebSocket未连接，消息已加入队列");
      this.messageQueue.push(messageToSend);
      // 尝试重新连接
      this.connect();
    }
  }

  /**
   * 清空消息队列，发送所有积压的消息
   */
  flushMessageQueue() {
    while (this.messageQueue.length > 0) {
      const message = this.messageQueue.shift();
      this.send(message);
    }
  }

  /**
   * 尝试重新连接WebSocket
   */
  attemptReconnect() {
    if (this.reconnectAttempts < this.options.maxReconnectAttempts) {
      this.reconnectAttempts++;
      console.log(
        `尝试重连 (${this.reconnectAttempts}/${this.options.maxReconnectAttempts})...`
      );

      setTimeout(() => {
        this.connect();
      }, this.reconnectInterval);
    } else {
      console.error("WebSocket重连失败，已达到最大重试次数");
      this.onError({
        type: "reconnect_failed",
        message: "WebSocket重连失败，已达到最大重试次数",
      });
    }
  }

  /**
   * 断开WebSocket连接
   */
  disconnect() {
    if (this.ws) {
      this.ws.close();
      this.ws = null;
      this.isConnected = false;
      this.updateConnectionState(this.connectionState.DISCONNECTED);
      this.messageQueue = [];
      this.reconnectAttempts = 0;

      // 清除连接超时定时器
      if (this.connectionTimer) {
        clearTimeout(this.connectionTimer);
        this.connectionTimer = null;
      }
    }
  }

  /**
   * 错误处理方法
   * @param {object} error - 错误对象
   */
  onError(error) {
    console.error("WebSocket服务错误:", error);
    this.callbacks.onError.forEach((callback) => callback(error));
  }

  /**
   * 注册事件回调
   * @param {string} event - 事件类型 (onOpen, onMessage, onError, onClose, onStateChange)
   * @param {Function} callback - 回调函数
   */
  on(event, callback) {
    if (!this.callbacks[event]) {
      this.callbacks[event] = [];
    }
    this.callbacks[event].push(callback);
  }

  /**
   * 移除事件回调
   * @param {string} event - 事件类型
   * @param {Function} callback - 要移除的回调函数
   */
  off(event, callback) {
    if (this.callbacks[event]) {
      this.callbacks[event] = this.callbacks[event].filter(
        (cb) => cb !== callback
      );
    }
  }

  /**
   * 获取当前连接状态
   * @returns {boolean} 连接状态
   */
  getConnectionStatus() {
    return this.isConnected;
  }

  /**
   * 获取当前连接状态字符串
   * @returns {string} 连接状态字符串
   */
  getConnectionState() {
    return this.currentState;
  }

  /**
   * 获取当前配置选项
   * @returns {object} 配置对象
   */
  getOptions() {
    return { ...this.options };
  }

  /**
   * 获取WebSocket URL
   * @returns {string} WebSocket URL
   */
  getUrl() {
    return this.wsUrl;
  }

  /**
   * 更新配置选项
   * @param {object} newOptions - 新的配置选项
   */
  updateOptions(newOptions) {
    this.options = { ...this.options, ...newOptions };
  }

  /**
   * 连接打开事件监听器
   * @param {Function} callback - 回调函数
   */
  onopen(callback) {
    this.on("onOpen", callback);
  }

  /**
   * 接收消息事件监听器
   * @param {Function} callback - 回调函数
   */
  onmessage(callback) {
    this.on("onMessage", callback);
  }

  /**
   * 错误事件监听器
   * @param {Function} callback - 回调函数
   */
  onerror(callback) {
    this.on("onError", callback);
  }

  /**
   * 自定义的数据处理事件回调
   * @param {Function} callback - 回调函数
   */
  static onProcessedData(callback) {
    //判断是否已注册，已注册则覆盖旧的回调函数
    const index = onProcessedEvent.indexOf(callback);
    if (index !== -1) {
      console.warn("回调函数已注册，无需重复注册");
      onProcessedEvent[index] = callback;
      return;
    } else onProcessedEvent.push(callback);
  }

  /**
   * 删除自定义的数据处理事件回调
   * @param {Function} callback - 回调函数
   */
  static offProcessedData(callback) {
    //不要使用filter，使用slice删除指定元素
    const index = onProcessedEvent.indexOf(callback);
    if (index !== -1) {
      onProcessedEvent.splice(index, 1);
    }
  }

  /**
   * 连接关闭事件监听器
   * @param {Function} callback - 回调函数
   */
  onclose(callback) {
    this.on("onClose", callback);
  }

  /**
   * 连接状态变化事件监听器
   * @param {Function} callback - 回调函数
   */
  onstatechange(callback) {
    this.on("onStateChange", callback);
  }

  /**
   * 静态方法：处理WebSocket连接收到的消息数据
   * @param {string} jsonMessage - JSON格式的消息字符串
   * @returns {object} 处理后的映射对象，格式为{"参数标识":[数值]}
   */
  static processWebSocketMessage(jsonMessage) {
    try {
      // 解析JSON消息
      const message =
        typeof jsonMessage === "string" ? JSON.parse(jsonMessage) : jsonMessage;

      // 提取必要字段
      const { com, data, selected } = message;

      // 验证必要字段是否存在
      if (
        !data ||
        !Array.isArray(data) ||
        !selected ||
        !Array.isArray(selected)
      ) {
        console.error("消息格式不正确：缺少必要字段data或selected");
        return {};
      }

      // 创建结果映射对象
      const resultMap = {};

      // 初始化所有selected参数的数组
      selected.forEach((param) => {
        resultMap[param] = [];
      });

      // 遍历data数组中的每个对象
      data.forEach((dataObj) => {
        // 检查data对象是否包含values字段
        if (!dataObj.values) {
          console.warn("数据对象缺少values字段");
          return;
        }

        // 使用":"作为分隔符，将values字符串分割为数值数组
        const valuesArray = dataObj.values.split(":");

        // 将分割后的数值与selected数组按位置一一对应
        valuesArray.forEach((valueStr, index) => {
          // 确保索引在selected数组范围内
          if (index < selected.length) {
            const paramKey = selected[index];
            const numericValue = parseFloat(valueStr);

            // 确保数值转换有效
            if (!isNaN(numericValue)) {
              resultMap[paramKey].push(numericValue);
            } else {
              console.warn(`无法将值"${valueStr}"转换为数字，索引：${index}`);
            }
          }
        });
      });

      return resultMap;
    } catch (error) {
      console.error("处理WebSocket消息时发生错误:", error);
      return {};
    }
  }

  /**
   * 处理后的数据事件监听器
   * @param {Function} callback - 回调函数，接收处理后的数据对象
   */
  onprocesseddata(callback) {
    this.on("onProcessedData", callback);
  }
}

// 导出StartModelWebSocketService类，支持创建多个独立实例
export default StartModelWebSocketService;
